#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QSerialPort>
#include <QSerialPortInfo>
#include <QDebug>
#include <QMessageBox>
#include <QSqlDatabase>
#include <QSqlQuery>

MainWindow::MainWindow(QWidget* parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QList<QSerialPortInfo> list = QSerialPortInfo::availablePorts();
    for (const QSerialPortInfo& info : list) {
        ui->comboBox->addItem(info.portName());
    }

    ui->baudRateView->setText("115200");
    ui->dataBitView->setText("8");
    ui->commandListWidget->setContextMenuPolicy(Qt::CustomContextMenu);

    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName("commands.db");
    if (!db.open()) {
        qDebug() << "Failed to open database";
        return;
    }
    query = new QSqlQuery(db);
    query->exec("CREATE TABLE IF NOT EXISTS commands (id INTEGER PRIMARY KEY, command TEXT, remark TEXT)");

    if (!query->exec("SELECT id, command, remark FROM commands")) {
        qDebug() << "查询失败";
        return;
    }

    QList<QString> commands;
    while (query->next()) {
        QString command = query->value(1).toString();
        QString remark = query->value(2).toString();

//        qDebug() << "ID:" << id << "Command:" << command << "Remark:" << remark;

        commands.append(command);
    }

    for (QString command : commands) {
        QByteArray array = QByteArray::fromHex(command.remove(" ").toUtf8());
        update_command_listWidget(array);
    }
}

static unsigned char highByte(const int value)
{
    return value >> 8 & 0xFF;
}

static unsigned char lowByte(const int value)
{
    return value & 0xFF;
}

MainWindow::~MainWindow()
{
    if (serialPort.isOpen()) {
        serialPort.close();  // 关闭串口
    }
    delete ui;
}

void MainWindow::read_SerialPort_Data()
{
    update_response_listWidget(serialPort.readAll());
}

QString MainWindow::format_hex_string(const QByteArray& data)
{
    QString hex = data.toHex().toUpper();

    QString hexWithSpaces;
    for (int i = 0; i < hex.length(); i += 2) {
        hexWithSpaces += hex.mid(i, 2) + " ";
    }

    if (!hexWithSpaces.isEmpty()) {
        hexWithSpaces.chop(1);
    }
    return hexWithSpaces;
}

void MainWindow::on_openSerialPortButton_clicked()
{
    if(serialPort.isOpen()) {
        serialPort.close();
        ui->openSerialPortButton->setText("打开串口");
    } else {
        if(ui->comboBox->currentText().isEmpty()) {
            QMessageBox::critical(this, "错误提示", "请选择要打开的串口名！");
            return;
        }

        if(ui->baudRateView->text().isEmpty()) {
            QMessageBox::critical(this, "错误提示", "波特率设置错误！");
            return;
        }

        if(ui->dataBitView->text().isEmpty()) {
            QMessageBox::critical(this, "错误提示", "数据位设置错误！");
            return;
        }

        QString baudRateStr = ui->baudRateView->text();
        bool ok;
        int baudRate = baudRateStr.toInt(&ok);
        if (!ok) {
            QMessageBox::critical(this, "错误", "无效的波特率值！");
            return;
        }

        serialPort.setPortName(ui->comboBox->currentText());
        serialPort.setBaudRate(baudRate);
        serialPort.setDataBits(QSerialPort::Data8);  // 设置数据位为 8 位
        serialPort.setParity(QSerialPort::NoParity);  // 设置无校验位
        serialPort.setStopBits(QSerialPort::OneStop);  // 设置停止位为 1 位
        serialPort.setFlowControl(QSerialPort::NoFlowControl);  // 设置无流控制
        if (serialPort.open(QIODevice::ReadWrite)) {  // 以读写模式打开串口
            ui->openSerialPortButton->setText("关闭串口");
            connect(&serialPort, &QSerialPort::readyRead, this, &MainWindow::read_SerialPort_Data);
        } else {
            QMessageBox::critical(this, "错误", serialPort.errorString());
        }
    }
}


void MainWindow::on_powerOnButton_clicked()
{
    if(serialPort.isOpen()) {
        const unsigned char command_data[] = {0xFE, 0xFE, 0x02, 0x10, 0xFA};
        QByteArray command(reinterpret_cast<const char*>(command_data), sizeof(command_data));
        serialPort.write(command);
    } else {
        QMessageBox::critical(this, "错误", "串口未打开");
    }
}

void MainWindow::on_powerOffButton_clicked()
{
    if(serialPort.isOpen()) {
        const unsigned char command_data[] = {0xFE, 0xFE, 0x02, 0x11, 0xFA};
        QByteArray command(reinterpret_cast<const char*>(command_data), sizeof(command_data));
        serialPort.write(command);
    } else {
        QMessageBox::critical(this, "错误", "串口未打开");
    }
}

void MainWindow::on_resetPositionButton_clicked()
{
    if(serialPort.isOpen()) {
        const unsigned char command_data[] = {
            0xFE, 0xFE, 0x0F, 0x3C,
            0x08, 0x00, 0x08, 0x00, 0x08, 0x00,
            0x08, 0x00, 0x08, 0x00, 0x08, 0x00,
            0x14, 0xFA
        };
        QByteArray command(reinterpret_cast<const char*>(command_data), sizeof(command_data));
        serialPort.write(command);
        update_command_listWidget(command);
    } else {
        QMessageBox::critical(this, "错误", "串口未打开");
    }
}

void MainWindow::on_queryElectronicButton_clicked()
{
    if(serialPort.isOpen()) {
        const unsigned char command_data[] = {0xFE, 0xFE, 0x02, 0x3D, 0xFA};
        QByteArray command(reinterpret_cast<const char*>(command_data), sizeof(command_data));
        serialPort.write(command);
    } else {
        QMessageBox::critical(this, "错误", "串口未打开");
    }
}

void MainWindow::on_queryAngleButton_clicked()
{
    if(serialPort.isOpen()) {
        const unsigned char command_data[] = {0xFE, 0xFE, 0x02, 0x23, 0xFA};
        QByteArray command(reinterpret_cast<const char*>(command_data), sizeof(command_data));
        serialPort.write(command);
    } else {
        QMessageBox::critical(this, "错误", "串口未打开");
    }
}

void MainWindow::on_queryStatusButton_clicked()
{
    if(serialPort.isOpen()) {
        const unsigned char command_data[] = {0xFE, 0xFE, 0x02, 0x14, 0xFA};
        QByteArray command(reinterpret_cast<const char*>(command_data), sizeof(command_data));
        serialPort.write(command);
    } else {
        QMessageBox::critical(this, "错误", "串口未打开");
    }
}

void MainWindow::on_clearHistoryButton_clicked()
{
    ui->responseListWidget->clear();
}

void MainWindow::update_command_listWidget(const QByteArray& command)
{
    if(command == nullptr) {
        return;
    }
    ui->commandListWidget->setWordWrap(true);
    QString commandHexValue = format_hex_string(command);
    QList<QListWidgetItem*> foundItems = ui->commandListWidget->findItems(commandHexValue, Qt::MatchFlag::MatchExactly);
    if(foundItems.empty()) {
        ui->commandListWidget->addItem(commandHexValue);
    } else {
        for (QListWidgetItem* item : foundItems) {
            // 从当前列表中移除该项
            int row = ui->commandListWidget->row(item);
            ui->commandListWidget->takeItem(row);

            // 将该项重新添加到列表的末尾
            ui->commandListWidget->addItem(item);
        }
    }

    //去重
    query->prepare("SELECT command FROM commands WHERE command = :command");
    query->bindValue(":command", command);
    if (!query->exec()) {
        qDebug() << "查询失败";
        return;
    }

    if (!query->next()) {
        // 如果没有结果，说明指令不存在
        query->prepare("INSERT INTO commands (command) VALUES (:command)");
        query->bindValue(":command", commandHexValue);
        query->exec();
    } else {
        qDebug() << "该指令已存在";
    }
}

void MainWindow::update_response_listWidget(const QByteArray& data)
{
    if(data == nullptr) {
        return;
    }
//    qDebug() << "接收到的数据：" << format_hex_string(data);
    ui->responseListWidget->setWordWrap(true);
    ui->responseListWidget->addItem(format_hex_string(data));
}

void MainWindow::on_responseListWidget_itemClicked(QListWidgetItem* item)
{
    ui->commandLineEdit->setText(item->text());
}

void MainWindow::on_commandListWidget_itemClicked(QListWidgetItem* item)
{
    ui->commandLineEdit->setText(item->text());
}

void MainWindow::on_sendElectronicPointButton_clicked()
{
    if(serialPort.isOpen()) {
        //收电位：FE FE 0E 3D 07 FE 08 11 08 0C 08 0B 08 0D 08 09 FA
        //发电位：FE FE 0F 3C 07 FE 08 11 08 0C 08 0B 08 0D 08 09 1E FA

        //收坐标：FE FE 0E 23 06 D4 00 05 09 42 C3 A1 21 8F C3 B6 FA
        //发坐标：FE FE 10 25 00 00 00 00 00 00 00 00 00 00 00 00 1E FA
        QByteArray array = QByteArray::fromHex(ui->commandLineEdit->text().remove(" ").toUtf8());
        QByteArray command;
        if(0x3D == array[3]) { //发电位指令
            command.append(0xFE);
            command.append(0xFE);
            command.append(0x0F);
            command.append(0x3C);

            for (int i = 4; i <= 15; ++i) {
                command.append(array[i]);
            }

            command.append(0x1E);
            command.append(0xFA);
        } else if(0x23 == array[3]) { //发坐标
            command.append(0xFE);
            command.append(0xFE);
            command.append(0x10);
            command.append(0x25);

            for (int i = 4; i <= 15; ++i) {
                command.append(array[i]);
            }

            command.append(0x1E);
            command.append(0xFA);
        } else {
            command = array;
        }
        serialPort.write(command);
        update_command_listWidget(command);
    } else {
        QMessageBox::critical(this, "错误", "串口未打开");
    }
}

void MainWindow::on_commandLineEdit_textChanged(const QString& arg1)
{
    if(arg1 == nullptr) {
        return;
    }
    QByteArray array = QByteArray::fromHex(ui->commandLineEdit->text().remove(" ").toUtf8());
    if(0x3D == array[3] || 0x3C == array[3]) {
        ui->commandTypeLabel->setText("电位指令");
        ui->commandTypeLabel->setStyleSheet("color: red;");
    } else if(0x23 == array[3] || 0x25 == array[3]) {
        ui->commandTypeLabel->setText("坐标指令");
        ui->commandTypeLabel->setStyleSheet("color: red;");
    } else {
        ui->commandTypeLabel->setText("#!");
        ui->commandTypeLabel->setStyleSheet("color: black;");
    }
}


void MainWindow::on_commandListWidget_customContextMenuRequested(const QPoint& pos)
{
    QPoint globalPos = ui->commandListWidget->mapToGlobal(pos);
    menu = new QMenu(this);
    QAction* action = menu->addAction("删除指令");
    connect(action, &QAction::triggered, this, [this]() {
        QString commandHexValue = ui->commandListWidget->currentItem()->text();

        query->prepare("DELETE FROM commands WHERE command = :command");
        query->bindValue(":command", commandHexValue);
        query->exec();

        ui->commandListWidget->takeItem(ui->commandListWidget->currentRow());
    });
    menu->exec(globalPos);
}

